package crossover;

import java.util.LinkedList;
import java.util.List;



import ga.*;
import operations.Operation;
import util.DebugConfig;
import util.Log;
public abstract class CrossoverStrategy implements Crossover{
	protected abstract boolean getCrossoverFlag();
	protected abstract int[] getCrossoverPoints(int individual1_Size,int individual2_Size);
	
	
	public Individual[] crossOver(Individual individual1, Individual individual2) {
		if(DebugConfig.CrossOverClass){
			Log.log("--------------------individual1----------------------");
			Log.log(individual1.toString()+ " size:"+ individual1.getSize());
			Log.log("---------------------individual2---------------------");
			Log.log(individual2.toString()+ " size:"+ individual2.getSize());
		}
		Individual offspring1 =(Individual) individual1.clone();
		Individual offspring2 = (Individual) individual2.clone();

		if(this.getCrossoverFlag() == false)
			return new Individual[] { offspring1, offspring2 };
	
		int[] crossoverPoints =this.getCrossoverPoints(individual1.getStatements().size(),individual2.getStatements().size());
			if(DebugConfig.CrossOverClass){
				Log.log("------------------------------------------");
				Log.log("crossoverPoints-1: "+ crossoverPoints[0]);
				Log.log("crossoverPoints-2: "+ crossoverPoints[1]);
				Log.log("------------------------------------------");

			}
		if(crossoverPoints == null)
			throw new RuntimeException("The overriden method 'getCrossoverPoints()' returned a null value");
		//Perform the cross over
		for(int i = 0; i < crossoverPoints.length; i++) {
			
			if(i== 0){
				//offspring2
				List<Operation>  test= new LinkedList<Operation>();
				List<Operation>  ops=individual2.getStatements();
				 //clone
				test.addAll(ops.subList(0, crossoverPoints[i+1]));
				 ops=individual1.getStatements();
				 //append
				 test.addAll(ops.subList(crossoverPoints[i], ops.size()));
	//			System.out.println("offspring2:"+offspring2);
				offspring2=new Individual(offspring2.getInitialConstructors(),test);
			}
			else{
				//offspring1
				List<Operation>  test= new LinkedList<Operation>();
				 //clone
				List<Operation>  ops=individual1.getStatements();
				test.addAll(ops.subList(0, crossoverPoints[i-1]));
				 ops=individual2.getStatements();
					//append
				 test.addAll(ops.subList(crossoverPoints[i], ops.size()));
				offspring1=new Individual(offspring1.getInitialConstructors(),test);
			//	System.out.println("offspring1:"+offspring1);
			}

		}
		if(DebugConfig.CrossOverClass){
			Log.log("-----------------offspring1-------------------------");
			Log.log(offspring1.toString()+ " size:"+ offspring1.getSize());
			Log.log("---------------------offspring2---------------------");
			Log.log(offspring2.toString()+ " size:"+ offspring2.getSize());
		}

		return new Individual[] { offspring1, offspring2 };	
	}

}
